<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>火山引擎豆包Demo</title>
    <style>
      body {
        font-family: "Microsoft YaHei", sans-serif;
        max-width: 800px;
        margin: 0 auto;
        padding: 20px;
        line-height: 1.6;
        color: #333;
      }
      
      #chat-box {
        background-color: #f9f9f9;
        border-radius: 10px;
        padding: 25px;
        min-height: 400px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
      }
      
      /* 段落样式 */
      .paragraph {
        margin: 16px 0;
        text-align: justify;
      }
      
      /* 一级标题样式（对应###） */
      .level-1 {
        font-size: 20px;
        font-weight: bold;
        color: #2c3e50;
        margin: 24px 0 12px;
        padding-bottom: 4px;
        border-bottom: 2px solid #eee;
      }
      
      /* 二级标题样式（对应####） */
      .level-2 {
        font-size: 18px;
        font-weight: bold;
        color: #34495e;
        margin: 20px 0 10px;
        padding-left: 5px;
        border-left: 3px solid #3498db;
      }
      
      /* 三级标题样式（对应更高级别） */
      .level-3 {
        font-size: 17px;
        font-weight: bold;
        color: #34495e;
        margin: 18px 0 8px;
      }
      
      /* 列表项样式 */
      .list-item {
        margin: 8px 0 8px 20px;
        position: relative;
        padding-left: 25px;
      }
      
      .list-item::before {
        content: "•";
        position: absolute;
        left: 0;
        color: #3498db;
        font-weight: bold;
      }
      
      /* 加粗文本样式（对应**） */
      .bold-text {
        font-weight: bold;
        color: #e74c3c;
      }
      
      /* 注意事项样式 */
      .note {
        font-style: italic;
        color: #7f8c8d;
        padding: 10px 15px;
        background-color: #f8f9fa;
        border-radius: 5px;
        margin: 15px 0;
      }
      
      /* 打字光标动画 */
      .typing-cursor {
        display: inline-block;
        width: 10px;
        height: 18px;
        background-color: #333;
        animation: blink 1s infinite;
      }
      
      @keyframes blink {
        0%, 100% { opacity: 1; }
        50% { opacity: 0; }
      }
    </style>
  </head>
  <body>
    <div id="chat-box"></div>
  </body>

  <script src="https://cdn.staticfile.net/jquery/1.10.2/jquery.min.js"></script>
  <script>
    // 具体对话
    let data = {
      model: "doubao-seed-1-6-250615",
      stream: true, // 流式传输
      messages: [
        { role: "user", content: `
        下面是我多次考试的详细得分情况，每次考试的情况分别对应评分细则归类，评分细则，满分，得分。请根据我的成绩生成形成性评价（成绩整体趋势，优势表现（具体细节分析），不足与薄弱环节（具体问题剖析）），练习建议，与总结。第一次考试情况：总得分为5.50。详细内容：评分细则归类:操作过程评分细则记录麻醉的进针深度，选择合适的穿刺针，将穿刺针与麻醉针比量长度，夹闭穿刺针橡胶管
通过比针确认穿刺针进针深度满分：6得分：2.00评分细则归类:操作过程评分细则用2％利多卡因在下一肋骨上缘的穿刺点垂直进针，自皮肤至壁层胸膜逐层麻醉（先进针→回吸→无血→注射麻醉药物→进针），回抽出胸水说明进入胸膜腔满分：5得分：0.00评分细则归类:操作过程评分细则穿刺完毕，夹闭胶管，拔出穿刺针稍用力按压片刻满分：3得分：0.00评分细则归类:操作过程评分细则操作者左手拇指与示指固定穿刺部位皮肤，右手持穿刺针沿下一肋骨上缘麻醉处垂直进针，缓缓刺入，当针锋抵抗感突然消失时表示已穿过胸膜壁层达胸膜腔满分：8得分：0.00评分细则归类:操作过程评分细则用5ml注射器抽取2％利多卡因3～5ml，排气。双人核对麻药（名称，浓度，有效期）满分：2得分：0.00评分细则归类:操作过程评分细则铺盖无菌洞巾满分：2得分：0.00评分细则归类:操作前准备评分细则仪表端庄、服装整洁、洗手、戴口罩、帽子。自我介绍，核对患者信息满分：4得分：0.00评分细则归类:操作过程评分细则留取胸水送检（生化、常规、细菌培养、涂片或脱落细胞学、病理检查）满分：5得分：0.00评分细则归类:操作过程评分细则消毒穿刺点，覆盖无菌纱布，胶布固定。协助患者整理衣服，恢复体位满分：3得分：0.00评分细则归类:操作过程评分细则术前行胸部查体，确认胸水部位满分：4得分：0.00评分细则归类:操作前准备评分细则准备物品：
（1）治疗车上层：胸腔穿刺包（内附一次性胸腔穿刺针12#，16#、无菌洞巾、无菌敷料、50ml注射器1个、5ml注射器1个，无菌试管）、聚维酮碘、消毒棉签1包、局麻药（2％利多卡因5ml）、甲紫1瓶、无菌止血钳1个、500ml标本容器1个、胶布、无菌橡胶医用手套2副、听诊器，血压计
（2）治疗车下层：生活垃圾桶、医疗垃圾桶、锐器盒满分：3得分：0.00评分细则归类:操作过程评分细则拔出麻醉针，立即纱布按压穿刺点片刻满分：2得分：0.00评分细则归类:操作过程评分细则选择合适体位：患者骑跨在椅子上，双手臂伏于椅背上，前额伏于前臂上，充分暴露肋间隙。
卧床患者，可以采取高坡卧位，患侧略向健侧转，患者前臂上举抱于枕部，便于显露穿刺部位满分：4得分：0.00评分细则归类:操作后处理评分细则术后患者宣教：卧床休息半小时。保持穿刺位点清洁干燥，24h之内不要沾水。检验结果回报会第一时间告知沟通满分：5得分：0.00评分细则归类:操作后处理评分细则术后测量患者生命体征。书写操作记录满分：4得分：0.00评分细则归类:操作前准备评分细则确认患者存在胸腔穿刺适应证，无禁忌证，向患者及家属交代胸穿目的及风险，签署知情同意书
查看患者胸部影像学资料，血常规，血凝常规结果，询问有无麻醉药物过敏满分：5得分：2.00评分细则归类:操作过程评分细则助手戴无菌手套，用无菌止血钳协助固定胸穿针。操作者将胶管连接注射器，松开夹闭装置，缓慢抽取胸水
一次穿刺不成功应将穿刺针退至皮下，调整穿刺方向后重新进针。两次穿刺不成功应完全退出穿刺针，再次检查穿刺针通畅性后更换位点，直到有胸水抽出为止满分：6得分：0.00评分细则归类:操作前准备评分细则测量患者生命体征。告知患者注意事项。
叮嘱患者操作过程中避免剧烈咳嗽、变换体位。有任何不适时及时告知满分：5得分：1.50评分细则归类:操作后处理评分细则整理物品，医疗垃圾分类处置满分：5得分：0.00评分细则归类:操作过程评分细则穿刺点选择： 叩诊实音最明显部位为穿刺点，棉签蘸甲紫在皮肤上标记穿刺点
穿刺点：（1）选择肩胛线或腋后线第7、8肋间隙；腋中线第6、7肋间隙；腋前线第5肋间隙
（2）积液量少或为包裹性积液：超声定位穿刺
（3）抽气时穿刺部位一般选取锁骨中线第二肋间或腋中线第4、5肋间。
常用穿刺点为肩胛线第7、8肋间。
穿刺点在下一肋骨上缘，应避开局部皮肤感染灶满分：5得分：0.00评分细则归类:总体印象评分细则注重人文关怀，在操作前、中、后均与患者适当沟通，不重复穿刺；遵循无菌原则满分：5得分：0.00评分细则归类:操作过程评分细则打开穿刺包，戴无菌手套，检查穿刺针及麻醉针通畅性、密闭性满分：5得分：0.00评分细则归类:操作过程评分细则消毒：以穿刺点为中心，同心圆消毒，由中心向外，消毒直径范围15cm，聚维酮碘消毒2次，第2次范围小于第1次
消毒范围要足够，不回消，不留白，过程中注意消毒棉签不可倒置满分：4得分：0.00第一次考试情况：总得分为96.00。详细内容：评分细则归类:总体印象评分细则注重人文关怀，在操作前、中、后均与患者适当沟通
        ` },
      ],
	  thinking:{
         "type":"disabled"
     }
    };

    // 在原有代码基础上修改，处理接口返回的格式并应用样式
    const chatBox = document.getElementById("chat-box");
    let fullMessage = "";
    let currentParagraph = ""; // 跟踪当前段落内容
    
    async function streamChat() {
      try {
        const response = await fetch(
          "https://ark.cn-beijing.volces.com/api/v3/chat/completions",
          {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              Authorization: "Bearer fc9b5fc8-01dc-4ab9-ba20-29c0322c7bdd",
            },
            body: JSON.stringify(data),
          }
        );

        if (!response.ok) {
          throw new Error(`HTTP错误: ${response.status}`);
        }

        const reader = response.body.getReader();
        const decoder = new TextDecoder();

        while (true) {
          const { done, value } = await reader.read();
          if (done) {
            // 处理最后剩余的内容
            if (currentParagraph.trim()) {
              fullMessage += formatContent(currentParagraph);
            }
            renderMessage(fullMessage);
            document.querySelector(".typing-cursor")?.remove();
            break;
          }

          const chunk = decoder.decode(value);
          processChunk(chunk);
        }
      } catch (error) {
        chatBox.innerHTML = `<div class="error">发生错误: ${error.message}</div>`;
        console.error("错误:", error);
      }
    }

    function processChunk(chunk) {
      chunk.split("\n").forEach((line) => {
        if (line.startsWith("data: ")) {
          try {
            const data = JSON.parse(line.slice(6));
            if (data.choices?.[0]?.delta?.content) {
              const newContent = data.choices[0].delta.content;
              processNewContent(newContent);
            }
          } catch (e) {
            // 忽略解析错误
            if (!line.includes("[DONE]")) {
              console.warn("解析数据块失败:", e);
            }
          }
        }
      });
    }

    function processNewContent(content) {
      // 检查是否包含换行符
      if (content.includes("\n")) {
        const parts = content.split("\n");
        // 处理除最后一部分外的所有内容
        for (let i = 0; i < parts.length - 1; i++) {
          currentParagraph += parts[i];
          // 结束当前段落并格式化
          fullMessage += formatContent(currentParagraph);
          currentParagraph = "";
        }
        // 处理最后一部分
        currentParagraph += parts[parts.length - 1];
      } else {
        currentParagraph += content;
      }
      
      // 实时渲染
      renderMessage(fullMessage + formatContent(currentParagraph, true));
    }

    // 格式化内容：替换Markdown标记为HTML标签
    function formatContent(content, isTemporary = false) {
      if (!content.trim()) return "";
      
      let formatted = content;
      
      // 处理一级标题（###）
      formatted = formatted.replace(/###\s+/g, '</div><div class="level-1">');
      
      // 处理二级标题（####）
      formatted = formatted.replace(/####\s+/g, '</div><div class="level-2">');
      
      // 处理三级标题（#####）
      formatted = formatted.replace(/#####\s+/g, '</div><div class="level-3">');
      
      // 处理加粗文本（**...**）
      formatted = formatted.replace(/\*\*(.*?)\*\*/g, '<span class="bold-text">$1</span>');
      
      // 处理列表项（- ）
      formatted = formatted.replace(/-(?=\s)/g, '</div><div class="list-item">');
      
      // 处理段落
      if (!formatted.startsWith('<div class="level-1">') && 
          !formatted.startsWith('<div class="level-2">') &&
          !formatted.startsWith('<div class="level-3">') &&
          !formatted.startsWith('<div class="list-item">')) {
        formatted = `<div class="paragraph">${formatted}</div>`;
      }
      
      // 闭合所有未闭合的标签
      formatted = formatted.replace(/(<div class="[^"]+">)(?=.*<\/div>)/g, '$1');
      
      return formatted;
    }

    function renderMessage(html) {
      // 确保所有标签正确闭合
      let safeHtml = html;
      if (safeHtml.includes('<div class="level-1">') && !safeHtml.includes('</div>')) {
        safeHtml += '</div>';
      }
      if (safeHtml.includes('<div class="level-2">') && !safeHtml.includes('</div>')) {
        safeHtml += '</div>';
      }
      if (safeHtml.includes('<div class="level-3">') && !safeHtml.includes('</div>')) {
        safeHtml += '</div>';
      }
      if (safeHtml.includes('<div class="list-item">') && !safeHtml.includes('</div>')) {
        safeHtml += '</div>';
      }
      if (safeHtml.includes('<div class="paragraph">') && !safeHtml.includes('</div>')) {
        safeHtml += '</div>';
      }
      
      chatBox.innerHTML = `
        ${safeHtml}
        <span class="typing-cursor"></span>
      `;
      // 滚动到底部
      chatBox.scrollTop = chatBox.scrollHeight;
    }

    streamChat();
  </script>
</body>
</html>
    